package cn.coderpig.cpfastaccessibility

import android.app.AlertDialog
import android.app.Notification
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.graphics.Color
import android.graphics.Point
import android.os.Build
import android.util.Log
import android.view.Gravity
import android.view.View
import android.view.WindowManager
import android.view.accessibility.AccessibilityEvent
import android.widget.TextView
import android.widget.Toast
import androidx.core.app.NotificationCompat
import cn.coderpig.cp_fast_accessibility.AnalyzeSourceResult
import cn.coderpig.cp_fast_accessibility.EventWrapper
import cn.coderpig.cp_fast_accessibility.FastAccessibilityService
import cn.coderpig.cp_fast_accessibility.FirmException
import cn.coderpig.cp_fast_accessibility.NodeWrapper
import cn.coderpig.cp_fast_accessibility.back
import cn.coderpig.cp_fast_accessibility.click
import cn.coderpig.cp_fast_accessibility.findAllNode
import cn.coderpig.cp_fast_accessibility.findNodeByExpression
import cn.coderpig.cp_fast_accessibility.findNodeById
import cn.coderpig.cp_fast_accessibility.findNodeByText
import cn.coderpig.cp_fast_accessibility.findNodesByIdNext
import cn.coderpig.cp_fast_accessibility.input
import cn.coderpig.cp_fast_accessibility.scrollForward
import com.alibaba.fastjson.JSON
import com.lzf.easyfloat.EasyFloat
import com.lzf.easyfloat.enums.ShowPattern
import com.lzf.easyfloat.enums.SidePattern
import kotlinx.coroutines.CoroutineExceptionHandler
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
import kotlinx.coroutines.suspendCancellableCoroutine
import kotlinx.coroutines.withContext
import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException


/**
 * Author: CoderPig
 * Date: 2023-03-24
 * Desc:
 */
class MyAccessibilityService : FastAccessibilityService() {
    companion object {
        private const val TAG = "CpFastAccessibility"
        const val CHANNEL_ID: String = "无障碍服务"
        const val NOTIFICATION_ID: Int = 1
        const val COMMENT_MAX_PAGE: Int = 3
    }

    override val enableListenApp = true
    private var foregroundNotification: Notification? = null
    private var tvLog: TextView? = null

    override fun onServiceConnected() {
        super.onServiceConnected()
        Log.e("CpFastAccessibility", "启动服务")
        Log.e(TAG, "onServiceConnected")
        showForegroundNotification("青鸾数字", "守护进程", "提示信息", activityClass = MainActivity::class.java)
        showFloatWindow()
    }

    override fun onDestroy() {
        super.onDestroy()
        closeForegroundNotification()
        EasyFloat.dismiss("MyAccessibilityService")
        tvLog = null
    }

    private fun startTest() {
        FastAccessibilityService.onAnalyzeSource(AccessibilityEvent.obtain(AccessibilityEvent.TYPE_VIEW_CLICKED).apply {
            className = "android.widget.FrameLayout"
            packageName = BuildConfig.APPLICATION_ID
        })
    }

    private var checkPackageName = "com.ss.android.ugc.aweme"
    private var appName = "抖音"

    private suspend fun suspendAnalyzeSource(): AnalyzeSourceResult {
        return super.suspendAnalyzeSource(checkPackageName, appName)
    }

    private var job: Job? = null
    private fun start() {
        if (job != null && job?.isActive == true) {
            Toast.makeText(appContext, "任务进行中，如需重新开始请先点击结束", Toast.LENGTH_LONG).show()
        }
        val exceptionHandler = CoroutineExceptionHandler { _, throwable ->
            Log.e(TAG, "异常", throwable)
            if (throwable is FirmException) {
                floatLog(throwable.message)
            } else {
                floatLog("程序运行异常，已停止")
            }
        }
        job = GlobalScope.launch(exceptionHandler) {
            withContext(Dispatchers.Main) {
                suspendCancellableCoroutine { coroutine ->
                    val mDialog = AlertDialog.Builder(this@MyAccessibilityService, android.R.style.Theme_DeviceDefault_Light_Dialog)
                        .setCancelable(false)
                        .setTitle("温馨提示")
                        .setMessage("请确定当前页面是：${appName}首页，否则无法运行。")
                        .setNegativeButton("取消") { _, _ ->
                            coroutine.resumeWithException(FirmException("点击取消,程序停止"))
                        }
                        .setPositiveButton("确定") { _, _ ->
                            coroutine.resume("")
                        }
                        .create()
                    // 关键：设置窗口类型为无障碍覆盖层
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                        mDialog.window?.setType(WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY);
                    } else {
                        mDialog.window?.setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
                    }
                    // 添加标志位确保显示在其他应用上方
                    mDialog.window?.addFlags(
                        WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE or
                                WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL or
                                WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
                    )
                    mDialog.show()
                }
            }
            val texts = JSON.parseArray(MyApp.sp.getString("texts", "[]"), MainActivity.Item::class.java)
            floatLog("本次运行关键字：${JSON.toJSONString(texts)}")
            while (isActive) {
                var result: AnalyzeSourceResult? = suspendAnalyzeSource()
                // 输出视频相关信息
                val videTitle = result?.findNodeByExpression {
                    it.id == "com.ss.android.ugc.aweme:id/title" && it.clickable && it.nodeInfo?.isVisibleToUser == true
                }
                val videDesc = result?.findNodeByExpression {
                    it.id == "com.ss.android.ugc.aweme:id/desc" && it.nodeInfo?.isVisibleToUser == true
                }
                floatLog(if (videTitle != null) "作者：${videTitle.text}" else null)
                floatLog(if (videDesc != null) "描述：${videDesc.text}" else null)
                //触发点击查看评论
                var commentContainer: NodeWrapper?
                var errorCut = 0
                while (true) {
                    result = suspendAnalyzeSource()
                    commentContainer = result.findNodeById("com.ss.android.ugc.aweme:id/comment_container") { it.nodeInfo?.isVisibleToUser == true }
                    if (commentContainer == null) {
                        delay(200)
                        floatLog("未获取到视频页面评论按钮")
                        // 统计次数超过多少次基本上是读取异常了退出任务或者重新开始
                        errorCut++
                        if (errorCut > 2) {
                            break
                        }
                    } else {
                        break
                    }
                }
                if (commentContainer == null) {
                    // 没有获取到直接下一个
//                    val screenSize = getRealScreenSize(appContext)
//                    swipe(screenSize.x / 4, screenSize.x / 5 * 4, screenSize.x / 4, screenSize.x / 5, 300)
                    result = suspendAnalyzeSource()
                    result.findNodeByExpression {
                        it.id == "com.ss.android.ugc.aweme:id/viewpager" && it.scrollable && it.description == "视频" && it.nodeInfo?.isVisibleToUser == true
                    }?.scrollForward()
                } else {
                    floatLog("获取到视频页面评论按钮点击打开评论页面")
                    // 点击评论
                    commentContainer.click()
                    delay(2000)
                    // 评论只读取10页
                    for (i in 1..COMMENT_MAX_PAGE) {
                        if (!isActive) {
                            break
                        }
                        // 读取评论
                        result = suspendAnalyzeSource()
                        val wdl = result.findNodeByText("登录看更多精彩评论", includeDesc = true)
                        if (wdl != null) {
                            throw FirmException("当前[${appName}],未登录账号，程序停止")
                        }
                        val dyUsers = userComment(result)
                        floatLog("读取到评论：${dyUsers.size}")
                        dyUsers.forEach { floatLog("读取到用户：${JSON.toJSONString(it)}") }
                        if (dyUsers.isNotEmpty()) {
                            for (dyUser in dyUsers) {
                                if (texts.any { dyUser.content?.contains(it.text) == true }) {
                                    floatLog("评论命中关键字：${JSON.toJSONString(dyUser)}")
                                    dyUser.avatarNode?.click()
                                    delay(2000)
                                    result = suspendAnalyzeSource()
                                    // 如果没有关注点击关注
                                    val ygz = result.findNodeByText("已关注", true, click = true)
                                    val wyz = result.findNodeByText("关注", true, click = true)
                                    val sx = result.findNodeByText("私信", true, click = true)
                                    // 没关注先点击关注
                                    if (wyz != null) {
                                        floatLog("没有关注触发关注")
                                        wyz.click()
                                        delay(1000)
                                        result = suspendAnalyzeSource()
                                        val qr = result.findNodeByExpression {
                                            it.id == "com.ss.android.ugc.aweme:id/qr"
                                                    && it.text == "确认" && it.clickable
                                        }
                                        if (qr != null) {
                                            floatLog("出现确认页面，点击确认")
                                            qr.click()
                                            delay(1000)
                                        }
                                    }
                                    floatLog("点击私信")
                                    // 点击发送私信进入私信页面
                                    sx?.click()
                                    delay(2000)
                                    // 判断是否发送过私信，发送过不要在发送
                                    val sx_centent = MyApp.sp.getString("sx_centent", null)
                                    floatLog("本次发送私信文本：${sx_centent}")
                                    if (!sx_centent.isNullOrBlank()) {
                                        result = suspendAnalyzeSource()
                                        val sxText =
                                            result.findNodeByExpression {
                                                it.id == "com.ss.android.ugc.aweme:id/content_layout"
                                                        && it.className == "android.widget.TextView"
                                                        && it.text == sx_centent
                                            }
                                        if (sxText == null) {
                                            floatLog("未发送过私信触发发送")
                                            result.findNodeById("com.ss.android.ugc.aweme:id/msg_et")?.input(sx_centent)
                                            delay(1000)
                                            result.findNodeByText("发送", includeDesc = true, descAllMatch = true, click = true)?.click()
                                            delay(1000)
                                        }
                                    }
                                    floatLog("结束私信页面返回两层到评论页面")
                                    // 返回两层，1次返回用户详情，2次返回到评论也
                                    back()
                                    delay(1000)
                                    back()
                                }
                            }
                        }
                        floatLog("当前页${i},处理完毕上滑一页${JSON.toJSONString(dyUsers)}")
                        delay(1000)
                        result = suspendAnalyzeSource()
                        val zsmygdNode = result.findNodeByText("暂时没有更多了", includeDesc = true)
                        if (zsmygdNode != null) {
                            break
                        }
                        // 滑动评论
                        result.findNodesByIdNext("com.ss.android.ugc.aweme:id/title", "条评论") { index: Int, node: NodeWrapper ->
                            index == 1
                        }?.scrollForward()
                        delay(2000)
                    }
                    floatLog("当前视频评论处理完返回视频页滑动加载下一个视频")
                    delay(2000)
                    back()
                    delay(2000)
                    // 首页滑动视频
//                    val screenSize = getRealScreenSize(appContext)
//                    swipe(screenSize.x / 2, screenSize.x / 5 * 4, screenSize.x / 2, screenSize.x / 5, 300)
                    result = suspendAnalyzeSource()
                    result.findNodeByExpression {
                        it.id == "com.ss.android.ugc.aweme:id/viewpager" && it.scrollable && it.description == "视频" && it.nodeInfo?.isVisibleToUser == true
                    }?.scrollForward()
                }
            }
        }
    }

    private fun end() {
        job?.cancel()
        job = null
        Toast.makeText(appContext, "取消成功，如需重新开始期待5秒钟", Toast.LENGTH_LONG).show()
    }

    private var lastText: String? = null

    private fun floatLog(text: String?) {
        if (text == null) {
            return
        }
        Log.e(TAG, text)
        tvLog?.post { tvLog?.text = "${lastText ?: ""}\n${text}" }
        lastText = text
    }

    override fun analyzeCallBack(wrapper: EventWrapper?, result: AnalyzeSourceResult) {
//  result.findNodeByText("搜索").click()
        //
        Log.e(TAG, "===>${result.nodes.firstOrNull()?.packageName}")
        Log.e(TAG, "触发无障碍")
        result.findAllNode().nodes.forEach { Log.e(TAG, "${it.id}<===>${it.clickable}<==>${it.className}=${it.text}<===>${it.description}") }
//        result.findNodesByIdNext("com.ss.android.ugc.aweme:id/viewpager") { index: Int, node: NodeWrapper -> index == 1 }?.scrollForward()

        val viewpager = result.findNodeByExpression {
            it.id == "com.ss.android.ugc.aweme:id/viewpager" && it.scrollable && it.description == "视频" && it.nodeInfo?.isVisibleToUser == true
        }
        Log.e(TAG, "ccccccccccccc${viewpager != null}")
        viewpager?.scrollForward()
        val videTitle = result.findNodeByExpression {
            it.id == "com.ss.android.ugc.aweme:id/title" && it.clickable && it.nodeInfo?.isVisibleToUser == true
        }
        val videDesc = result.findNodeByExpression {
            it.id == "com.ss.android.ugc.aweme:id/desc" && it.nodeInfo?.isVisibleToUser == true
        }
        Log.e(TAG, "${videTitle?.text}")
        Log.e(TAG, "${videDesc?.text}")
//        result.findNodesById("com.ss.android.ugc.aweme:id/desc").nodes
//            .forEach {
//                Log.e(
//                    TAG,
//                    "${it.nodeInfo?.isVisibleToUser}<----->${it.id}<=1111111111==>${it.clickable}<==>${it.className}=${it.text}<===>${it.description}"
//                )
//            }

        // 首页滑动视频
//        val screenSize = getRealScreenSize(this)
//        val startX = screenSize.x / 2
//        val height = screenSize.y / 4
//        Log.e(TAG, "${startX}<===>${screenSize.x / 5 * 4} <==>${screenSize.x / 5}")
//        swipe(screenSize.x / 2, screenSize.x / 5 * 4, screenSize.x / 2, screenSize.x / 5,300)

        // 触发点击查看评论
//        result.findNodeById("com.ss.android.ugc.aweme:id/comment_container") { it.nodeInfo?.isVisibleToUser == true }?.click()

        // 滑动评论
//        result.findNodesByIdNext("com.ss.android.ugc.aweme:id/title","条评论") { index: Int, node: NodeWrapper ->
//            index == 1
//        }?.scrollForward()

        // 去读评论，并点击头像
//        userComment(result)

        // 如果没有关注点击关注
        val ygz = result.findNodeByText("已关注", true, click = true)
        val wyz = result.findNodeByText("关注", true, click = true)
        val sx = result.findNodeByText("私信", true, click = true)
        Log.e(TAG, "===》${ygz != null}")
        Log.e(TAG, "===》${wyz != null}")
        Log.e(TAG, "===》${sx != null}")
//        result.findNodeByText("关注", true, click = true)?.click()
        val qr = result.findNodeByExpression { it.id == "com.ss.android.ugc.aweme:id/qr" && it.text == "确认" && it.clickable }

        Log.e(TAG, "qr===》${qr != null}")
//        sx?.click()
        // 点击发送私信进入私信页面
//        result.findNodeById("com.ss.android.ugc.aweme:id/msg_et")?.input("周六出去玩")
        // 判断是否发送过私信，发送过不要在发送
//        result.findNodeByText("发送", includeDesc = true, descAllMatch = true, click = true)?.click()

        val text =
            result.findNodeByExpression { it.id == "com.ss.android.ugc.aweme:id/content_layout" && it.className == "android.widget.TextView" }?.text
        Log.e(TAG, "text===》${text}")
        // 结束，回到评论页面

//        back()
    }

    private fun log(it: NodeWrapper) {
        Log.e(TAG, "${it.id}<===>${it.clickable}<==>${it.className}=${it.text}<===>${it.description}")
    }

    private fun userComment(result: AnalyzeSourceResult): MutableList<DyUser> {
        val id = "com.ss.android.ugc.aweme:id/title"
        val startComment = "条评论"
        var index = 0
        var startFlag = false
        var userStartFlag = false
        val dyUsers = mutableListOf<DyUser>()
        var mDyUser: DyUser? = null
        for (node in result.nodes) {
            if (startFlag) {
                if (!userStartFlag && node.id == "com.ss.android.ugc.aweme:id/avatar") {
                    userStartFlag = true
                    mDyUser = DyUser()
                    dyUsers.add(mDyUser)
                    mDyUser.avatarNode = node
                    mDyUser.avatar = node.text?.ifBlank { node.description }
                }
                if (userStartFlag && node.id == "com.ss.android.ugc.aweme:id/title") {
                    mDyUser?.title = node.text?.ifBlank { node.description }
                }
                if (userStartFlag && node.id == "com.ss.android.ugc.aweme:id/content") {
                    userStartFlag = false
                    mDyUser?.content = node.text?.ifBlank { node.description }
                }
            }
            if (startFlag) {
                index++
            }
            if (!node.id.isNullOrBlank()) {
                if (node.id!!.contains(id) && node.text?.contains(startComment) == true) {
                    Log.e("findNodesByIdNext", "${node.id}<===>${node.clickable}<==>${node.className}=${node.text}<===>${node.description}")
                    startFlag = true
                }
            }
        }
        return dyUsers
    }

    // 获取包含系统装饰的完整屏幕尺寸
    private fun getRealScreenSize(context: Context): Point {
        val windowManager = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager
        val point = Point()

        return when {
            Build.VERSION.SDK_INT >= Build.VERSION_CODES.R -> {
                val metrics = windowManager.currentWindowMetrics
                val bounds = metrics.bounds
                point.set(bounds.width(), bounds.height())
                point
            }

            Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1 -> {
                windowManager.defaultDisplay?.getRealSize(point)
                point
            }

            else -> {
                val display = windowManager.defaultDisplay
                point.x = display?.width ?: 0
                point.y = display?.height ?: 0
                point
            }
        }
    }

    private fun showForegroundNotification(
        title: String = "通知标题",
        content: String = "通知内容",
        ticker: String = "通知提示语",
        iconRes: Int = R.mipmap.ic_launcher,
        activityClass: Class<*>? = null
    ) {
        val context = instance
        Log.e("CpFastAccessibility", "context=>$context")
        val channelName = "前台服务通知" // 定义渠道名称

        // 创建通知渠道
        val notificationManager = instance?.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
        Log.e("CpFastAccessibility", "notificationManager--${notificationManager}")
        Log.e("CpFastAccessibility", "notificationManager--${notificationManager.areNotificationsEnabled()}")
        val channel = NotificationChannel(
            CHANNEL_ID,
            channelName,
            NotificationManager.IMPORTANCE_HIGH // 修正常量名
        ).apply {
            enableLights(true)          // 开启指示灯
            lightColor = Color.BLUE     // 设置指示灯颜色
            enableVibration(true)       // 开启震动
            vibrationPattern = longArrayOf(100, 200, 300, 400) // 修正数组类型
            setShowBadge(true)          // 显示角标
            setBypassDnd(true)
            lockscreenVisibility = Notification.VISIBILITY_PRIVATE // 锁屏可见性
        }
        notificationManager.createNotificationChannel(channel)

        // 构建通知
        foregroundNotification = NotificationCompat.Builder(appContext, CHANNEL_ID).apply {
            setSmallIcon(iconRes)
            setContentTitle(title)
            setContentText(content)
            setTicker(ticker)
            priority = NotificationCompat.PRIORITY_MIN // 设置低优先级

            // 添加点击跳转
            activityClass?.let {
                val intent = Intent(context, it)
                val pendingIntent = PendingIntent.getActivity(
                    context,
                    0,
                    intent,
                    PendingIntent.FLAG_IMMUTABLE // 修正标志名
                )
                setContentIntent(pendingIntent)
            }
        }.build()

        Log.e("CpFastAccessibility", "启动前台服务")
        // 启动前台服务
        startForeground(NOTIFICATION_ID, foregroundNotification) // 需要唯一通知ID
    }

    private fun closeForegroundNotification() {
        foregroundNotification?.let { stopForeground(true) }
    }

    private fun showFloatWindow() {
        EasyFloat.with(this)
            .setLayout(R.layout.layout_float_window) {
                it.findViewById<View>(R.id.button_start).setOnClickListener {
                    start()
//                    startTest()
                }
                it.findViewById<View>(R.id.button_end).setOnClickListener {
                    Log.e("findViewById", "button_end")
                    end()
                }
                tvLog = it.findViewById(R.id.tv_log)
            }
            .setShowPattern(ShowPattern.ALL_TIME)
            .setSidePattern(SidePattern.RESULT_RIGHT)
            .setTag("MyAccessibilityService")
            .setGravity(Gravity.BOTTOM or Gravity.RIGHT)
            .setLayoutChangedGravity(Gravity.END)
            .setMatchParent(widthMatch = false, heightMatch = false)
            .show()
    }
}